1장: 리액트 개발을 위해 꼭 알아야 할 자바스크립트
동등 비교
자바스크립트에서의 동등 비교
자바스크립트의 데이터 타입
데이터 타입을 구분하는 가장 큰 차이점은 값을 저장하는 방식이며 이 방식의 차이가 동등 비교를 할 때 차이를 만드는 원인이 된다.
원시타입은 불변형의 값으로 저장되며, 이 값은 변수 할당 시점에 메모리 영역을 차 지하고 저장된다. 객체는 프로퍼티를 삭제, 추가,
수정할 수 있으므로 원시의 값과 다르게 변경 가능한 형태로 저장되며, 값을 복사할 때도 값이 아닌 참조를 전달하게 된다.
- 원시 타입
○ boolean
○ null
○ undefined
○ number
○ string
○ symbol
○ bigint
//느슨한 비교
console.log(5 == "5"); // true
console.log(0 == false); // true
console.log(null == undefined); // true
//엄격한 비교
let bar1 = 'hello world'
let bar2 = bar1
console.log(bar1 === bar2) // true
- 객체 타입
○ object
var foo1 = {
bar: 'hello',
}
var foo2 = {
bar:'hello',
}
console.log(foo1 ===foo2) //false
console.log(foo1.bar ===foo2.bar) //true
- Object.is()와 ===의 차이점
//NaN 비교
console.log(NaN === NaN); // false
console.log(Object.is(NaN, NaN)); // true
const value = NaN;
console.log(value === NaN); // false
console.log(Object.is(value, NaN)); // true
//+0 vs -0 비교
console.log(+0 === -0); // true
console.log(Object.is(+0, -0)); // false
const balance = -0;
if (Object.is(balance, -0)) {
console.log("Negative zero detected!");
}
변수를 비교하거나 음수를 구별해야 하는 상황에 유용하게 쓰인다.
리액트에서의 동등 비교
- object.is() 활용
import { useState } from "react";
function App() {
const [count, setCount] = useState(0);
console.log(Object.is(count, -0)); // 함수를 호출하면 Object.is(0, -0) 비교가 수행됨 0 !== -0이므로 리렌더링 발생
return (
<div>
<button onClick={() => setCount(-0)}>Set -0</button>
</div>
);
}
변수와 함수에 조건식을 붙여 다양한 방식으로 활용이 가능하다.
- shallowEqual() 개념
1 depth(객체의 속성값이 원시값) 까지의 비교가 가능해진다.
2 depth(객체안의 다른 객체) 의 경우false
를 반 환한다.
import React from "react";
//memo를 사용해서 느슨한 비교를 수행하고 비교 후 신규 데이터 입력시(false) 렌더링.
const MyComponent = React.memo(({ data }) => {
console.log("Rendered!");
return <div>{data.hello}</div>;
});
export default function App() {
const obj1 = { hello: "world" };
const obj2 = { hello: "world" };
return (
<>
<MyComponent data={obj1} /> {/* 최 초 렌더링 */} //true
<MyComponent data={obj2} /> {/* 주소가 다르기 때문에 리렌더링 */} //false
<MyComponent data={{ hello: "world" }} /> {/* 새로운 객체 → 렌더링 발생 */} //false
</>
);
}
함수
함수 선언문
값이 표현되지 않았기 때문에 표현식이 아닌 일반문으로 분류되며, 선언 전에 호출이 가능하고 function 키워드를 사용해 별도로 선언한다.
hello(); //정상 실행
function hello() {
console.log('hello world')
}
hello(); //정상 실행
함수 표현식
hello(); //오류 발생 (Cannot access 'hello' before initialization)
const hello = function () {
console.log('hello world')
}
hello(); //정상 실행
변수를 선언하고 함수를 값으로 할당하며 선언 후에만 호출이 가능하다. 표현식은 함수 내부에서만 유효한 식별자이기 때문에 가독성을 위해 이름을 붙이지 않는다.
화살표 함수
const hello = () => {
console.log("Hello, world!");
};
hello(); // 정상 실행
ES6에서 새롭게 추가된 함수 생성방식으로, function 대신 => 화살표를 사용해서 코드 길이를 줄여 간결하게 표현하였다.
const person = {
name: "Alice",
sayHello: () => {
console.log(`Hello, ${this.name}`);
}
};
person.sayHello(); // Hello, undefined
this
가 필요한 객체 메서드에는 부적합하다.
const func = () => {
console.log(arguments);
};
func(1, 2, 3); // ReferenceError: arguments is not defined
const func = (...args) => {
console.log(args);
};
func(1, 2, 3); // [1, 2, 3]
arguments 객체를 지원하지 않는다.
import React, { Component } from "react";
class App extends Component {
state = {
count: 0,
};
render() {
return (
<div>
<h1>Count: {this.state.count}</h1>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
+
</button>
</div>
);
}
}
export default App;
화살표 함수를 사용하면 this
를 별도로 바인딩 할 필요 없이 사용가능하기 때문에 안정적으로 setState
를 호출할 수 있다.
다양한 함수 살펴보기
- 즉시 실행 함수: 함수를 정의하고 그 순간 실행되는 함수이며 재호출이 불가능하다. 이 특성을 이용해서 독립적 함수 스코프를 운용할 수 있다.
(function () {
console.log("hello world");
})();
(() => {
console.log("hello world");
})();
- 고차 함수: 함수를 인수로 받거나 새로움 함수를 반환시킬 수 있다. 리액트에서는 컴포넌트를 인수로 받아 새로운 함수 컴포넌트로 반환한다.
const squares = numbers.map(num => num * num);
console.log(squares); // [1, 4, 9, 16, 25]
const evens = numbers.filter(num => num % 2 === 0);
console.log(evens); // [2, 4]
function applyOperation(a, b, operation) {
return operation(a, b);
}
function add(x, y) {
return x + y;
}
function multiply(x, y) {
return x * y;
}
console.log(applyOperation(5, 3, add)); // 8
console.log(applyOperation(5, 3, multiply)); // 15
- 함수를 만들 때 주의사항
○ 함수의 부수 효과를 최대한 억제하라. (외부에 끼치는 영향을 억제하고 실행 결과를 예측가능하게 만들어야 한다.)
○ 코드의 길이를 줄여라. 하나의 함수가 너무 많은 일을 하지 않아야 함수의 원래 목적인 재사용성을 높일 수 있다.
○ 함수의 이름을 간결하고 이해하기 쉽게 만들어라.
클래스
생성자, 속성, 함수를 모아 정의하는 템플릿이며 하나만 존재할 수 있다.
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
const alice = new Person("Alice", 25);
console.log(alice.name); // "Alice"
console.log(alice.age); // 25